今天要開始往資料庫塞資料,再也不能忽視之前那個連線失敗問題。
其實是因為我連線模式忘了選擇,更正確的說,我當初沒找到選擇的地方,所以被預設成 Remote
了。
打開資料庫設定頁面後,點擊 Connection type 旁邊的藍色文字會看到可以選的四個選項。
和 H2 官網 http://www.h2database.com/html/features.html 不同,官網是把連線模式和儲存資料做組合, IDE Intellij idea 簡化了選項。
IDE選項 | 和官網比對 |
---|---|
remote | Server 連線(帳密登入) + persistent 儲存資料 |
in-memory | Embedded 連線 + in-memory 儲存資料 |
Embedded | Embedded 連線 + persistent 儲存資料 |
URL only | Server 連線 + persistent 儲存資料 |
因為開發中資料庫欄位常需要變動,所以選擇 in-memory
,這樣每次連線結束
都會清掉資料庫。
接著為了在程式中執行 jdbc 連線,所以要在 build.gradle
新增 Library 。
implementation "org.jetbrains.exposed:exposed-jdbc:$exposed_version"
這樣就可以建立 Topics table 了!
連線資訊複製資料庫設定頁面的地方, mem
就是 in-memory
的意思。
Database.connect("jdbc:h2:mem:default", driver = "org.h2.Driver")
transaction {
SchemaUtils.create(Topics)
}
接下來我把亂數資料放進資料庫,因為每個 transaction 區塊是一個整體。如果其中一行壞了,整個 transaction 都會回復成執行前的樣子,所以我把它和建立 table 的程式碼分開。
transaction {
for (i in 0..10) {
Topic.new {
title = "從前從前有碗" + listOf("海龜湯", "孟婆湯", "玉米湯", "南瓜湯").random()
description = "$title......\n$title......"
completed = false
tags = ""
createdAt = DateTime.now()
updatedAt = DateTime.now()
}
}
}
原本在 Api 產生亂數標題資料的地方,改成從資料庫讀取。
get("/api/topics") {
val topics = transaction {
Topic.all().map {
TopicResponse(
id = it.id.value,
name = it.title,
avatar = "https://imgur.com/l0swFL1.jpg",
attendance = (0..10).random().toString() + "人"
)
}
}
call.respond(topics)
}
結果執行後卻沒有顯示資料,檢查發現是 Table not found
錯誤,這時候想起來少做了一個 DB_CLOSE_DELAY
設定,沒做設定的時候每個 transaction 一執行完就會關閉連線,然後資料就被清空了。
Database.connect("jdbc:h2:mem:default;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
新設定可以保持連線狀態,也就能達成在 Ktor 服務中止時才清空資料的目的。
雖然今天的進度就 App 的角度來看沒有變化,但是對 server 來說,建立、查詢題目 Api 的重要基礎已經打好,很快就能和 App 真實互動。
本次鐵人賽的作品在放進更多內容後已經成書,書名是《老姐要用Kotlin寫專案:從 Server 到 Android APP 的開發生存日記》,歡迎購買唷。https://www.tenlong.com.tw/products/9789864348978